<?php

if (! defined ( 'BASEPATH' ))
	exit ( 'No direct script access allowed' );
/**
 * CodeIgniter
 *
 * An open source application development framework for PHP 5.1.6 or newer
 *
 * @package		CodeIgniter
 * @author		ExpressionEngine Dev Team
 * @copyright	Copyright (c) 2008 - 2011, EllisLab, Inc.
 * @license		http://codeigniter.com/user_guide/license.html
 * @link		http://codeigniter.com
 * @since		Version 1.0
 * @filesource
 */

// ------------------------------------------------------------------------


/**
 * Form Validation Class
 *
 * @package		CodeIgniter
 * @subpackage	Libraries
 * @category	Validation
 * @author		ExpressionEngine Dev Team
 * @link		http://codeigniter.com/user_guide/libraries/form_validation.html
 */
class CI_Form_validation {
	
	var $CI;
	var $_field_data = array ();
	var $_config_rules = array ();
	var $_error_array = array ();
	var $_error_messages = array ();
	var $_error_prefix = '<p>';
	var $_error_suffix = '</p>';
	var $error_string = '';
	var $_safe_form_data = FALSE;
	
	/**
	 * Constructor
	 */
	public function __construct($rules = array()) {
		$this->CI = & get_instance ();
		
		// Validation rules can be stored in a config file.
		$this->_config_rules = $rules;
		
		// Automatically load the form helper
		$this->CI->load->helper ( 'form' );
		
		// Set the character encoding in MB.
		if (function_exists ( 'mb_internal_encoding' )) {
			mb_internal_encoding ( $this->CI->config->item ( 'charset' ) );
		}
		
		log_message ( 'debug', "Form Validation Class Initialized" );
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Set Rules
	 *
	 * This function takes an array of field names and validation
	 * rules as input, validates the info, and stores it
	 *
	 * @access	public
	 * @param	mixed
	 * @param	string
	 * @return	void
	 */
	function set_rules($field, $label = '', $rules = '') {
		// No reason to set rules if we have no POST data
		if (count ( $_POST ) == 0) {
			return $this;
		}
		
		// If an array was passed via the first parameter instead of indidual string
		// values we cycle through it and recursively call this function.
		if (is_array ( $field )) {
			foreach ( $field as $row ) {
				// Houston, we have a problem...
				if (! isset ( $row ['field'] ) or ! isset ( $row ['rules'] )) {
					continue;
				}
				
				// If the field label wasn't passed we use the field name
				$label = (! isset ( $row ['label'] )) ? $row ['field'] : $row ['label'];
				
				// Here we go!
				$this->set_rules ( $row ['field'], $label, $row ['rules'] );
			}
			return $this;
		}
		
		// No fields? Nothing to do...
		if (! is_string ( $field ) or ! is_string ( $rules ) or $field == '') {
			return $this;
		}
		
		// If the field label wasn't passed we use the field name
		$label = ($label == '') ? $field : $label;
		
		// Is the field name an array?  We test for the existence of a bracket "[" in
		// the field name to determine this.  If it is an array, we break it apart
		// into its components so that we can fetch the corresponding POST data later
		if (strpos ( $field, '[' ) !== FALSE and preg_match_all ( '/\[(.*?)\]/', $field, $matches )) {
			// Note: Due to a bug in current() that affects some versions
			// of PHP we can not pass function call directly into it
			$x = explode ( '[', $field );
			$indexes [] = current ( $x );
			
			for($i = 0; $i < count ( $matches ['0'] ); $i ++) {
				if ($matches ['1'] [$i] != '') {
					$indexes [] = $matches ['1'] [$i];
				}
			}
			
			$is_array = TRUE;
		} else {
			$indexes = array ();
			$is_array = FALSE;
		}
		
		// Build our master array
		$this->_field_data [$field] = array ('field' => $field, 'label' => $label, 'rules' => $rules, 'is_array' => $is_array, 'keys' => $indexes, 'postdata' => NULL, 'error' => '' );
		
		return $this;
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Set Error Message
	 *
	 * Lets users set their own error messages on the fly.  Note:  The key
	 * name has to match the  function name that it corresponds to.
	 *
	 * @access	public
	 * @param	string
	 * @param	string
	 * @return	string
	 */
	function set_message($lang, $val = '') {
		if (! is_array ( $lang )) {
			$lang = array ($lang => $val );
		}
		
		$this->_error_messages = array_merge ( $this->_error_messages, $lang );
		
		return $this;
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Set The Error Delimiter
	 *
	 * Permits a prefix/suffix to be added to each error message
	 *
	 * @access	public
	 * @param	string
	 * @param	string
	 * @return	void
	 */
	function set_error_delimiters($prefix = '<p>', $suffix = '</p>') {
		$this->_error_prefix = $prefix;
		$this->_error_suffix = $suffix;
		
		return $this;
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Get Error Message
	 *
	 * Gets the error message associated with a particular field
	 *
	 * @access	public
	 * @param	string	the field name
	 * @return	void
	 */
	function error($field = '', $prefix = '', $suffix = '') {
		if (! isset ( $this->_field_data [$field] ['error'] ) or $this->_field_data [$field] ['error'] == '') {
			return '';
		}
		
		if ($prefix == '') {
			$prefix = $this->_error_prefix;
		}
		
		if ($suffix == '') {
			$suffix = $this->_error_suffix;
		}
		
		return $prefix . $this->_field_data [$field] ['error'] . $suffix;
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Error String
	 *
	 * Returns the error messages as a string, wrapped in the error delimiters
	 *
	 * @access	public
	 * @param	string
	 * @param	string
	 * @return	str
	 */
	function error_string($prefix = '', $suffix = '') {
		// No errrors, validation passes!
		if (count ( $this->_error_array ) === 0) {
			return '';
		}
		
		if ($prefix == '') {
			$prefix = $this->_error_prefix;
		}
		
		if ($suffix == '') {
			$suffix = $this->_error_suffix;
		}
		
		// Generate the error string
		$str = '';
		foreach ( $this->_error_array as $val ) {
			if ($val != '') {
				$str .= $prefix . $val . $suffix . "\n";
			}
		}
		
		return $str;
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Run the Validator
	 *
	 * This function does all the work.
	 *
	 * @access	public
	 * @return	bool
	 */
	function run($group = '') {
		// Do we even have any data to process?  Mm?
		if (count ( $_POST ) == 0) {
			return FALSE;
		}
		
		// Does the _field_data array containing the validation rules exist?
		// If not, we look to see if they were assigned via a config file
		if (count ( $this->_field_data ) == 0) {
			// No validation rules?  We're done...
			if (count ( $this->_config_rules ) == 0) {
				return FALSE;
			}
			
			// Is there a validation rule for the particular URI being accessed?
			$uri = ($group == '') ? trim ( $this->CI->uri->ruri_string (), '/' ) : $group;
			
			if ($uri != '' and isset ( $this->_config_rules [$uri] )) {
				$this->set_rules ( $this->_config_rules [$uri] );
			} else {
				$this->set_rules ( $this->_config_rules );
			}
			
			// We're we able to set the rules correctly?
			if (count ( $this->_field_data ) == 0) {
				log_message ( 'debug', "Unable to find validation rules" );
				return FALSE;
			}
		}
		
		// Load the language file containing error messages
		$this->CI->lang->load ( 'form_validation' );
		
		// Cycle through the rules for each field, match the
		// corresponding $_POST item and test for errors
		foreach ( $this->_field_data as $field => $row ) {
			// Fetch the data from the corresponding $_POST array and cache it in the _field_data array.
			// Depending on whether the field name is an array or a string will determine where we get it from.
			

			if ($row ['is_array'] == TRUE) {
				$this->_field_data [$field] ['postdata'] = $this->_reduce_array ( $_POST, $row ['keys'] );
			} else {
				if (isset ( $_POST [$field] ) and $_POST [$field] != "") {
					$this->_field_data [$field] ['postdata'] = $_POST [$field];
				}
			}
			
			$this->_execute ( $row, explode ( '|', $row ['rules'] ), $this->_field_data [$field] ['postdata'] );
		}
		
		// Did we end up with any errors?
		$total_errors = count ( $this->_error_array );
		
		if ($total_errors > 0) {
			$this->_safe_form_data = TRUE;
		}
		
		// Now we need to re-set the POST data with the new, processed data
		$this->_reset_post_array ();
		
		// No errors, validation passes!
		if ($total_errors == 0) {
			return TRUE;
		}
		
		// Validation fails
		return FALSE;
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Traverse a multidimensional $_POST array index until the data is found
	 *
	 * @access	private
	 * @param	array
	 * @param	array
	 * @param	integer
	 * @return	mixed
	 */
	function _reduce_array($array, $keys, $i = 0) {
		if (is_array ( $array )) {
			if (isset ( $keys [$i] )) {
				if (isset ( $array [$keys [$i]] )) {
					$array = $this->_reduce_array ( $array [$keys [$i]], $keys, ($i + 1) );
				} else {
					return NULL;
				}
			} else {
				return $array;
			}
		}
		
		return $array;
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Re-populate the _POST array with our finalized and processed data
	 *
	 * @access	private
	 * @return	null
	 */
	function _reset_post_array() {
		foreach ( $this->_field_data as $field => $row ) {
			if (! is_null ( $row ['postdata'] )) {
				if ($row ['is_array'] == FALSE) {
					if (isset ( $_POST [$row ['field']] )) {
						$_POST [$row ['field']] = $this->prep_for_form ( $row ['postdata'] );
					}
				} else {
					// start with a reference
					$post_ref = & $_POST;
					
					// before we assign values, make a reference to the right POST key
					if (count ( $row ['keys'] ) == 1) {
						$post_ref = & $post_ref [current ( $row ['keys'] )];
					} else {
						foreach ( $row ['keys'] as $val ) {
							$post_ref = & $post_ref [$val];
						}
					}
					
					if (is_array ( $row ['postdata'] )) {
						$array = array ();
						foreach ( $row ['postdata'] as $k => $v ) {
							$array [$k] = $this->prep_for_form ( $v );
						}
						
						$post_ref = $array;
					} else {
						$post_ref = $this->prep_for_form ( $row ['postdata'] );
					}
				}
			}
		}
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Executes the Validation routines
	 *
	 * @access	private
	 * @param	array
	 * @param	array
	 * @param	mixed
	 * @param	integer
	 * @return	mixed
	 */
	function _execute($row, $rules, $postdata = NULL, $cycles = 0) {
		// If the $_POST data is an array we will run a recursive call
		if (is_array ( $postdata )) {
			foreach ( $postdata as $key => $val ) {
				$this->_execute ( $row, $rules, $val, $cycles );
				$cycles ++;
			}
			
			return;
		}
		
		// --------------------------------------------------------------------
		

		// If the field is blank, but NOT required, no further tests are necessary
		$callback = FALSE;
		if (! in_array ( 'required', $rules ) and is_null ( $postdata )) {
			// Before we bail out, does the rule contain a callback?
			if (preg_match ( "/(callback_\w+)/", implode ( ' ', $rules ), $match )) {
				$callback = TRUE;
				$rules = (array ('1' => $match [1] ));
			} else {
				return;
			}
		}
		
		// --------------------------------------------------------------------
		

		// Isset Test. Typically this rule will only apply to checkboxes.
		if (is_null ( $postdata ) and $callback == FALSE) {
			if (in_array ( 'isset', $rules, TRUE ) or in_array ( 'required', $rules )) {
				// Set the message type
				$type = (in_array ( 'required', $rules )) ? 'required' : 'isset';
				
				if (! isset ( $this->_error_messages [$type] )) {
					if (FALSE === ($line = $this->CI->lang->line ( $type ))) {
						$line = 'The field was not set';
					}
				} else {
					$line = $this->_error_messages [$type];
				}
				
				// Build the error message
				$message = sprintf ( $line, $this->_translate_fieldname ( $row ['label'] ) );
				
				// Save the error message
				$this->_field_data [$row ['field']] ['error'] = $message;
				
				if (! isset ( $this->_error_array [$row ['field']] )) {
					$this->_error_array [$row ['field']] = $message;
				}
			}
			
			return;
		}
		
		// --------------------------------------------------------------------
		

		// Cycle through each rule and run it
		foreach ( $rules as $rule ) {
			$_in_array = FALSE;
			
			// We set the $postdata variable with the current data in our master array so that
			// each cycle of the loop is dealing with the processed data from the last cycle
			if ($row ['is_array'] == TRUE and is_array ( $this->_field_data [$row ['field']] ['postdata'] )) {
				// We shouldn't need this safety, but just in case there isn't an array index
				// associated with this cycle we'll bail out
				if (! isset ( $this->_field_data [$row ['field']] ['postdata'] [$cycles] )) {
					continue;
				}
				
				$postdata = $this->_field_data [$row ['field']] ['postdata'] [$cycles];
				$_in_array = TRUE;
			} else {
				$postdata = $this->_field_data [$row ['field']] ['postdata'];
			}
			
			// --------------------------------------------------------------------
			

			// Is the rule a callback?
			$callback = FALSE;
			if (substr ( $rule, 0, 9 ) == 'callback_') {
				$rule = substr ( $rule, 9 );
				$callback = TRUE;
			}
			
			// Strip the parameter (if exists) from the rule
			// Rules can contain a parameter: max_length[5]
			$param = FALSE;
			if (preg_match ( "/(.*?)\[(.*)\]/", $rule, $match )) {
				$rule = $match [1];
				$param = $match [2];
			}
			
			// Call the function that corresponds to the rule
			if ($callback === TRUE) {
				if (! method_exists ( $this->CI, $rule )) {
					continue;
				}
				
				// Run the function and grab the result
				$result = $this->CI->$rule ( $postdata, $param );
				
				// Re-assign the result to the master data array
				if ($_in_array == TRUE) {
					$this->_field_data [$row ['field']] ['postdata'] [$cycles] = (is_bool ( $result )) ? $postdata : $result;
				} else {
					$this->_field_data [$row ['field']] ['postdata'] = (is_bool ( $result )) ? $postdata : $result;
				}
				
				// If the field isn't required and we just processed a callback we'll move on...
				if (! in_array ( 'required', $rules, TRUE ) and $result !== FALSE) {
					continue;
				}
			} else {
				if (! method_exists ( $this, $rule )) {
					// If our own wrapper function doesn't exist we see if a native PHP function does.
					// Users can use any native PHP function call that has one param.
					if (function_exists ( $rule )) {
						$result = $rule ( $postdata );
						
						if ($_in_array == TRUE) {
							$this->_field_data [$row ['field']] ['postdata'] [$cycles] = (is_bool ( $result )) ? $postdata : $result;
						} else {
							$this->_field_data [$row ['field']] ['postdata'] = (is_bool ( $result )) ? $postdata : $result;
						}
					} else {
						log_message ( 'debug', "Unable to find validation rule: " . $rule );
					}
					
					continue;
				}
				
				$result = $this->$rule ( $postdata, $param );
				
				if ($_in_array == TRUE) {
					$this->_field_data [$row ['field']] ['postdata'] [$cycles] = (is_bool ( $result )) ? $postdata : $result;
				} else {
					$this->_field_data [$row ['field']] ['postdata'] = (is_bool ( $result )) ? $postdata : $result;
				}
			}
			
			// Did the rule test negatively?  If so, grab the error.
			if ($result === FALSE) {
				if (! isset ( $this->_error_messages [$rule] )) {
					if (FALSE === ($line = $this->CI->lang->line ( $rule ))) {
						$line = 'Unable to access an error message corresponding to your field name.';
					}
				} else {
					$line = $this->_error_messages [$rule];
				}
				
				// Is the parameter we are inserting into the error message the name
				// of another field?  If so we need to grab its "field label"
				if (isset ( $this->_field_data [$param] ) and isset ( $this->_field_data [$param] ['label'] )) {
					$param = $this->_translate_fieldname ( $this->_field_data [$param] ['label'] );
				}
				
				// Build the error message
				$message = sprintf ( $line, $this->_translate_fieldname ( $row ['label'] ), $param );
				
				// Save the error message
				$this->_field_data [$row ['field']] ['error'] = $message;
				
				if (! isset ( $this->_error_array [$row ['field']] )) {
					$this->_error_array [$row ['field']] = $message;
				}
				
				return;
			}
		}
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Translate a field name
	 *
	 * @access	private
	 * @param	string	the field name
	 * @return	string
	 */
	function _translate_fieldname($fieldname) {
		// Do we need to translate the field name?
		// We look for the prefix lang: to determine this
		if (substr ( $fieldname, 0, 5 ) == 'lang:') {
			// Grab the variable
			$line = substr ( $fieldname, 5 );
			
			// Were we able to translate the field name?  If not we use $line
			if (FALSE === ($fieldname = $this->CI->lang->line ( $line ))) {
				return $line;
			}
		}
		
		return $fieldname;
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Get the value from a form
	 *
	 * Permits you to repopulate a form field with the value it was submitted
	 * with, or, if that value doesn't exist, with the default
	 *
	 * @access	public
	 * @param	string	the field name
	 * @param	string
	 * @return	void
	 */
	function set_value($field = '', $default = '') {
		if (! isset ( $this->_field_data [$field] )) {
			return $default;
		}
		
		// If the data is an array output them one at a time.
		//     E.g: form_input('name[]', set_value('name[]');
		if (is_array ( $this->_field_data [$field] ['postdata'] )) {
			return array_shift ( $this->_field_data [$field] ['postdata'] );
		}
		
		return $this->_field_data [$field] ['postdata'];
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Set Select
	 *
	 * Enables pull-down lists to be set to the value the user
	 * selected in the event of an error
	 *
	 * @access	public
	 * @param	string
	 * @param	string
	 * @return	string
	 */
	function set_select($field = '', $value = '', $default = FALSE) {
		if (! isset ( $this->_field_data [$field] ) or ! isset ( $this->_field_data [$field] ['postdata'] )) {
			if ($default === TRUE and count ( $this->_field_data ) === 0) {
				return ' selected="selected"';
			}
			return '';
		}
		
		$field = $this->_field_data [$field] ['postdata'];
		
		if (is_array ( $field )) {
			if (! in_array ( $value, $field )) {
				return '';
			}
		} else {
			if (($field == '' or $value == '') or ($field != $value)) {
				return '';
			}
		}
		
		return ' selected="selected"';
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Set Radio
	 *
	 * Enables radio buttons to be set to the value the user
	 * selected in the event of an error
	 *
	 * @access	public
	 * @param	string
	 * @param	string
	 * @return	string
	 */
	function set_radio($field = '', $value = '', $default = FALSE) {
		if (! isset ( $this->_field_data [$field] ) or ! isset ( $this->_field_data [$field] ['postdata'] )) {
			if ($default === TRUE and count ( $this->_field_data ) === 0) {
				return ' checked="checked"';
			}
			return '';
		}
		
		$field = $this->_field_data [$field] ['postdata'];
		
		if (is_array ( $field )) {
			if (! in_array ( $value, $field )) {
				return '';
			}
		} else {
			if (($field == '' or $value == '') or ($field != $value)) {
				return '';
			}
		}
		
		return ' checked="checked"';
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Set Checkbox
	 *
	 * Enables checkboxes to be set to the value the user
	 * selected in the event of an error
	 *
	 * @access	public
	 * @param	string
	 * @param	string
	 * @return	string
	 */
	function set_checkbox($field = '', $value = '', $default = FALSE) {
		if (! isset ( $this->_field_data [$field] ) or ! isset ( $this->_field_data [$field] ['postdata'] )) {
			if ($default === TRUE and count ( $this->_field_data ) === 0) {
				return ' checked="checked"';
			}
			return '';
		}
		
		$field = $this->_field_data [$field] ['postdata'];
		
		if (is_array ( $field )) {
			if (! in_array ( $value, $field )) {
				return '';
			}
		} else {
			if (($field == '' or $value == '') or ($field != $value)) {
				return '';
			}
		}
		
		return ' checked="checked"';
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Required
	 *
	 * @access	public
	 * @param	string
	 * @return	bool
	 */
	function required($str) {
		if (! is_array ( $str )) {
			return (trim ( $str ) == '') ? FALSE : TRUE;
		} else {
			return (! empty ( $str ));
		}
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Performs a Regular Expression match test.
	 *
	 * @access	public
	 * @param	string
	 * @param	regex
	 * @return	bool
	 */
	function regex_match($str, $regex) {
		if (! preg_match ( $regex, $str )) {
			return FALSE;
		}
		
		return TRUE;
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Match one field to another
	 *
	 * @access	public
	 * @param	string
	 * @param	field
	 * @return	bool
	 */
	function matches($str, $field) {
		if (! isset ( $_POST [$field] )) {
			return FALSE;
		}
		
		$field = $_POST [$field];
		
		return ($str !== $field) ? FALSE : TRUE;
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Minimum Length
	 *
	 * @access	public
	 * @param	string
	 * @param	value
	 * @return	bool
	 */
	function min_length($str, $val) {
		if (preg_match ( "/[^0-9]/", $val )) {
			return FALSE;
		}
		
		if (function_exists ( 'mb_strlen' )) {
			return (mb_strlen ( $str ) < $val) ? FALSE : TRUE;
		}
		
		return (strlen ( $str ) < $val) ? FALSE : TRUE;
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Max Length
	 *
	 * @access	public
	 * @param	string
	 * @param	value
	 * @return	bool
	 */
	function max_length($str, $val) {
		if (preg_match ( "/[^0-9]/", $val )) {
			return FALSE;
		}
		
		if (function_exists ( 'mb_strlen' )) {
			return (mb_strlen ( $str ) > $val) ? FALSE : TRUE;
		}
		
		return (strlen ( $str ) > $val) ? FALSE : TRUE;
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Exact Length
	 *
	 * @access	public
	 * @param	string
	 * @param	value
	 * @return	bool
	 */
	function exact_length($str, $val) {
		if (preg_match ( "/[^0-9]/", $val )) {
			return FALSE;
		}
		
		if (function_exists ( 'mb_strlen' )) {
			return (mb_strlen ( $str ) != $val) ? FALSE : TRUE;
		}
		
		return (strlen ( $str ) != $val) ? FALSE : TRUE;
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Valid Email
	 *
	 * @access	public
	 * @param	string
	 * @return	bool
	 */
	function valid_email($str) {
		return (! preg_match ( "/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $str )) ? FALSE : TRUE;
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Valid Emails
	 *
	 * @access	public
	 * @param	string
	 * @return	bool
	 */
	function valid_emails($str) {
		if (strpos ( $str, ',' ) === FALSE) {
			return $this->valid_email ( trim ( $str ) );
		}
		
		foreach ( explode ( ',', $str ) as $email ) {
			if (trim ( $email ) != '' && $this->valid_email ( trim ( $email ) ) === FALSE) {
				return FALSE;
			}
		}
		
		return TRUE;
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Validate IP Address
	 *
	 * @access	public
	 * @param	string
	 * @return	string
	 */
	function valid_ip($ip) {
		return $this->CI->input->valid_ip ( $ip );
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Alpha
	 *
	 * @access	public
	 * @param	string
	 * @return	bool
	 */
	function alpha($str) {
		return (! preg_match ( "/^([a-z])+$/i", $str )) ? FALSE : TRUE;
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Alpha-numeric
	 *
	 * @access	public
	 * @param	string
	 * @return	bool
	 */
	function alpha_numeric($str) {
		return (! preg_match ( "/^([a-z0-9])+$/i", $str )) ? FALSE : TRUE;
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Alpha-numeric with underscores and dashes
	 *
	 * @access	public
	 * @param	string
	 * @return	bool
	 */
	function alpha_dash($str) {
		return (! preg_match ( "/^([-a-z0-9_-])+$/i", $str )) ? FALSE : TRUE;
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Numeric
	 *
	 * @access	public
	 * @param	string
	 * @return	bool
	 */
	function numeric($str) {
		return ( bool ) preg_match ( '/^[\-+]?[0-9]*\.?[0-9]+$/', $str );
	
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Is Numeric
	 *
	 * @access	public
	 * @param	string
	 * @return	bool
	 */
	function is_numeric($str) {
		return (! is_numeric ( $str )) ? FALSE : TRUE;
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Integer
	 *
	 * @access	public
	 * @param	string
	 * @return	bool
	 */
	function integer($str) {
		return ( bool ) preg_match ( '/^[\-+]?[0-9]+$/', $str );
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Decimal number
	 *
	 * @access	public
	 * @param	string
	 * @return	bool
	 */
	function decimal($str) {
		return ( bool ) preg_match ( '/^[\-+]?[0-9]+\.[0-9]+$/', $str );
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Greather than
	 *
	 * @access	public
	 * @param	string
	 * @return	bool
	 */
	function greater_than($str, $min) {
		if (! is_numeric ( $str )) {
			return FALSE;
		}
		return $str > $min;
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Less than
	 *
	 * @access	public
	 * @param	string
	 * @return	bool
	 */
	function less_than($str, $max) {
		if (! is_numeric ( $str )) {
			return FALSE;
		}
		return $str < $max;
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Is a Natural number  (0,1,2,3, etc.)
	 *
	 * @access	public
	 * @param	string
	 * @return	bool
	 */
	function is_natural($str) {
		return ( bool ) preg_match ( '/^[0-9]+$/', $str );
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Is a Natural number, but not a zero  (1,2,3, etc.)
	 *
	 * @access	public
	 * @param	string
	 * @return	bool
	 */
	function is_natural_no_zero($str) {
		if (! preg_match ( '/^[0-9]+$/', $str )) {
			return FALSE;
		}
		
		if ($str == 0) {
			return FALSE;
		}
		
		return TRUE;
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Valid Base64
	 *
	 * Tests a string for characters outside of the Base64 alphabet
	 * as defined by RFC 2045 http://www.faqs.org/rfcs/rfc2045
	 *
	 * @access	public
	 * @param	string
	 * @return	bool
	 */
	function valid_base64($str) {
		return ( bool ) ! preg_match ( '/[^a-zA-Z0-9\/\+=]/', $str );
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Prep data for form
	 *
	 * This function allows HTML to be safely shown in a form.
	 * Special characters are converted.
	 *
	 * @access	public
	 * @param	string
	 * @return	string
	 */
	function prep_for_form($data = '') {
		if (is_array ( $data )) {
			foreach ( $data as $key => $val ) {
				$data [$key] = $this->prep_for_form ( $val );
			}
			
			return $data;
		}
		
		if ($this->_safe_form_data == FALSE or $data === '') {
			return $data;
		}
		
		return str_replace ( array ("'", '"', '<', '>' ), array ("&#39;", "&quot;", '&lt;', '&gt;' ), stripslashes ( $data ) );
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Prep URL
	 *
	 * @access	public
	 * @param	string
	 * @return	string
	 */
	function prep_url($str = '') {
		if ($str == 'http://' or $str == '') {
			return '';
		}
		
		if (substr ( $str, 0, 7 ) != 'http://' && substr ( $str, 0, 8 ) != 'https://') {
			$str = 'http://' . $str;
		}
		
		return $str;
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Strip Image Tags
	 *
	 * @access	public
	 * @param	string
	 * @return	string
	 */
	function strip_image_tags($str) {
		return $this->CI->input->strip_image_tags ( $str );
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * XSS Clean
	 *
	 * @access	public
	 * @param	string
	 * @return	string
	 */
	function xss_clean($str) {
		return $this->CI->security->xss_clean ( $str );
	}
	
	// --------------------------------------------------------------------
	

	/**
	 * Convert PHP tags to entities
	 *
	 * @access	public
	 * @param	string
	 * @return	string
	 */
	function encode_php_tags($str) {
		return str_replace ( array ('<?php', '<?PHP', '<?', '?>' ), array ('&lt;?php', '&lt;?PHP', '&lt;?', '?&gt;' ), $str );
	}

}
// END Form Validation Class

/* End of file Form_validation.php */
/* Location: ./system/libraries/Form_validation.php */
